import { Body, Controller, Get, Post, Query, Res, UseGuards } from "@nestjs/common";
import { LoginStrDto, LoginDto, LogOutDto } from "./dto/loginDto";
import { WebURLConstants } from "src/WebURLConstant";
import { plainToInstance } from 'class-transformer'
import { validate } from "class-validator";
import { restBody } from "src/store/vo/BodyDto";
import { LoginService } from "./login.service";
import { JwtService } from "@nestjs/jwt";
import { log } from "console";
import { DecodePipe } from "src/utils/decode.pipe";
import { Response } from 'express'
import { encryptData } from "src/encrypt/encrypt";
import { AuthGuard } from "src/auth/guard/auth.guard";
import { RedisCacheService } from "src/redis/redis.service";

@Controller("")
export class LoginController {

  constructor(
    private loginService: LoginService,
    private jwtService: JwtService,
    private readonly redisCacheService: RedisCacheService
  ) { }

  /**
   * 生成验证码
   * @returns base64数据
   */
  @Get(WebURLConstants.V_CODE)
  async createVCode() {

    return this.loginService.createVCode()
  }

  /**
   * 用户登录
   * @param loginDto 用户名密码（加密）
   * @returns 返回用户信息（加密）
   */
  @Post(WebURLConstants.LOGIN)
  async login(@Body(DecodePipe) loginParams: LoginStrDto, @Res() res: Response) {

    // 校验解密后的参数
    const params = plainToInstance(LoginDto, loginParams)
    const errors = await validate(params);
    if (errors.length > 0) {
      return restBody(null, errors.toString(), 500)
    }

    log('login-body:', params)

    try {
      // 查询用户信息
      const userData = await this.loginService.getUserInfo(params);
      if (userData) {

        // 生成token，存储相关信息
        const payload = {
          userId: userData.id,
          orgId: userData.orgId,
          roleIds: userData.roles.map(item => item.id),
          loginName: userData.loginName
        }
        const token = await this.jwtService.signAsync(payload)
        // 存储 token 到 redis 中
        this.redisCacheService.set(userData.loginName + '_token', token, 1000 * 60 * 60 * 24)
        // 存储当前用户和所有下级Id(用作数据权限)
        this.redisCacheService.set(userData.loginName + '_userIds', await this.loginService.getOrgUserIds(userData.orgId), 1000 * 60 * 60 * 24)

        res.setHeader('Set-Cookie', `token=${token}; `)

        const data = await restBody(userData)
        // 返回加密信息
        return res.json({ params: encryptData(JSON.stringify(data)) });
      } else {
        throw new Error('获取用户信息失败')
      }
    } catch (error) {
      log('error:', error);
      return res.json(await restBody(null, error, 500));
    }
  }

  /**
   * 退出登录
   * @param query 用户账号
   * @returns 
   */
  @Get(WebURLConstants.LOG_OUT)
  @UseGuards(AuthGuard)
  async logOut(@Query() logOutDto: LogOutDto) {
    log('get-query:', logOutDto)

    const data = await this.loginService.logOut(logOutDto)

    return restBody(data)
  }
}